package com.info.zhiduoduo.admin.service;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.Condition;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.info.zhiduoduo.admin.model.formbean.crowdsource.TaxPaymentVoucherListFormBean;
import com.info.zhiduoduo.admin.model.formbean.entrust.EditEntrustProjectInvoiceFormBean;
import com.info.zhiduoduo.admin.model.formbean.companyParty.GetCompanyPartyFromBean;
import com.info.zhiduoduo.admin.model.formbean.invoice.*;
import com.info.zhiduoduo.common.configs.NotificationConfig;
import com.info.zhiduoduo.common.configs.UploadPathConfig;
import com.info.zhiduoduo.common.constants.Constants;
import com.info.zhiduoduo.common.constants.SmartResult;
import com.info.zhiduoduo.common.constants.StatusMsg;
import com.info.zhiduoduo.common.constants.invoice.InvoiceType;
import com.info.zhiduoduo.common.constants.project.ProjectType;
import com.info.zhiduoduo.common.exception.Asserts;
import com.info.zhiduoduo.common.exception.SmartException;
import com.info.zhiduoduo.common.formbean.BaseListFormBean;
import com.info.zhiduoduo.common.formbean.BaseSimpleFormBean;
import com.info.zhiduoduo.common.utils.DateUtil;
import com.info.zhiduoduo.common.utils.FileUtil;
import com.info.zhiduoduo.common.utils.LogUtil;
import com.info.zhiduoduo.common.utils.NumberUtil;
import com.info.zhiduoduo.common.utils.RandomUtil;
import com.info.zhiduoduo.common.utils.StringUtil;
import com.info.zhiduoduo.core.service.CommonService;
import com.info.zhiduoduo.core.service.CoreInvoiceService;
import com.info.zhiduoduo.core.service.InvoiceInventoryService;
import com.info.zhiduoduo.core.service.WxMessageService;
import com.info.zhiduoduo.core.service.common.BaseService;
import com.info.zhiduoduo.core.service.common.DocService;
import com.info.zhiduoduo.core.service.common.RedisService;
import com.info.zhiduoduo.core.service.impl.CeoNoticeService;
import com.info.zhiduoduo.repository.dto.crowdsource.*;
import com.info.zhiduoduo.repository.dto.invoice.*;
import com.info.zhiduoduo.repository.dto.maker.MakerDetailDto;
import com.info.zhiduoduo.repository.entity.company.Company;
import com.info.zhiduoduo.repository.entity.company.CompanyAccount;
import com.info.zhiduoduo.repository.entity.company.CompanyEntrustFile;
import com.info.zhiduoduo.repository.entity.company.CompanyProject;
import com.info.zhiduoduo.repository.entity.crowdsource.*;
import com.info.zhiduoduo.repository.entity.entrustmentproject.EntrustmentProject;
import com.info.zhiduoduo.repository.entity.entrustmentproject.EntrustmentProjectItem;
import com.info.zhiduoduo.repository.entity.invoice.*;
import com.info.zhiduoduo.repository.entity.maker.MakerAccount;
import com.info.zhiduoduo.repository.entity.maker.MakerStudio;
import com.info.zhiduoduo.repository.entity.quota.CityConfig;
import com.info.zhiduoduo.repository.entity.recharge.RechargeRecord;
import com.info.zhiduoduo.repository.entity.system.SystemManager;
import com.info.zhiduoduo.repository.entity.system.TaxSource;
import com.info.zhiduoduo.repository.entity.taxer.TaxerInvoice;
import com.info.zhiduoduo.repository.mapper.company.CompanyAccountMapper;
import com.info.zhiduoduo.repository.mapper.company.CompanyEntrustFileMapper;
import com.info.zhiduoduo.repository.mapper.company.CompanyMapper;
import com.info.zhiduoduo.repository.mapper.company.CompanyProjectMapper;
import com.info.zhiduoduo.repository.mapper.crowdsource.*;
import com.info.zhiduoduo.repository.mapper.invoice.*;

import com.info.zhiduoduo.repository.mapper.memorandum.PlatformMemorandumMapper;
import com.info.zhiduoduo.repository.mapper.system.TaxSourceMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;

import java.io.File;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import lombok.extern.slf4j.Slf4j;

/**
 * 发票管理
 *
 * @author bob
 * @since 2019/1/3 上午11:25
 */
@Slf4j
@Service
public class InvoiceService extends BaseService {

	@Autowired
	DocService docService;
	@Autowired
	WxMessageService wxMessageService;
	@Autowired
	CeoNoticeService ceoNoticeService;
	@Autowired
	RedisService redisService;
	@Autowired
	InvoiceInventoryService invoiceInventoryService;
	@Autowired
	CoreInvoiceService coreInvoiceService;
	@Autowired
	CrowdsourceService crowdsourceService;
	@Resource
	SystemService systemService;
	@Autowired
	MakerService makerService;

	@Resource
	InvoiceMapper invoiceMapper;
	@Resource
	CompanyProjectMapper companyProjectMapper;
	@Resource
	CrowdsourceProjectMapper crowdsourceProjectMapper;
	@Resource
	InvoiceInventoryMapper invoiceInventoryMapper;
	@Resource
	InvoiceInventoryRecordMapper invoiceInventoryRecordMapper;
	@Resource
	CompanyInventoryMapper companyInventoryMapper;
	@Resource
	CompanyInventoryRecordMapper companyInventoryRecordMapper;
	@Resource
	CrowdsourceAccountMapper crowdsourceAccountMapper;
	@Resource
	ContractorInvoiceMapper contractorInvoiceMapper;
	@Resource
	CrowdsourceInvoiceMapper crowdsourceInvoiceMapper;
	@Resource
	CompanyMapper companyMapper;
	@Resource
	CompanyEntrustFileMapper companyEntrustFileMapper;
	@Resource
	CompanyAccountMapper companyAccountMapper;
	@Resource
	PurchaseInformationMapper purchaseInformationMapper;
	@Resource
	PurchaseInvoiceRecordMapper purchaseInvoiceRecordMapper;
	@Resource
	TaxPaymentVoucherMapper taxPaymentVoucherMapper;
	@Resource
	OverdueTaxFormMapper overdueTaxFormMapper;
	@Resource
	TaxSourceMapper taxSourceMapper;
	@Resource
	PlatformMemorandumMapper platformMemorandumMapper;

	@Resource
	CommonService commonService;

	@Resource
	UploadPathConfig uploadPathConfig;
	@Autowired
	NotificationConfig notificationConfig;

	/**
	 * 待开发票列表, 获取已验证过的项目列表
	 */
	public SmartResult invoiceList(BaseSimpleFormBean<InvoiceListFromBean> formBean) {

		int userid = formBean.getUserid();
		InvoiceListFromBean reqdata = formBean.getReqdata();
		if (userid <= 0 || reqdata == null) return errorParamSmartResult();

		SystemManager systemManager = new SystemManager().selectById(userid);
		if (null == systemManager || systemManager.getState() != 1) {
			return smartResult(StatusMsg.StatusMsg_128);
		}
		//操作人员对接城市
		String city = systemManager.getDockingCity();
		// 发票 创客按自身的开户地区分
		String dockingCity = StringUtil.isEmpty(city) ? "" : " and ma.opening_location in (" + city + ") ";

		Date startDate = reqdata.getStartDate();
		Date endDate = reqdata.getEndDate();
		String name = reqdata.getName();
		String projectType = reqdata.getProjectType();
		Integer temporaryLogin = reqdata.getTemporaryLogin();
		int partyId = reqdata.getPartyId();
		int state = reqdata.getState();
		if (startDate == null) startDate = new Date(0);
		if (endDate == null) endDate = new Date();

		List<InvoiceBriefDto> list;
		Page<InvoiceBriefDto> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());

		list = invoiceMapper.getBriefList(projectType, name, state, startDate, endDate, dockingCity, temporaryLogin, partyId,0);
		//当前查询条数的总金额
		BigDecimal sumPrice = list.stream().map(InvoiceBriefDto::getInvoiceAmount).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
		//获取创客季度金额
		Set<Integer> userId =  new HashSet<>();
		//获取企业策略性内容
		Set<Integer> companyId =  new HashSet<>();
		for (InvoiceBriefDto dto:list){
			companyId.add(dto.getCompid());
			userId.add(dto.getUserid());
		}
		Map<Integer,String> map = getSpecialNeedsContent(companyId,2);
		Map<Integer,BigDecimal> bigDecimalMap = obtainQuarterlyAmount(userId);
		Map<Integer,Integer> mapUser = getNoPolicyBilling(userId,1);
		Map<Integer,Integer> mapCompany = getNoPolicyBilling(companyId,2);
		//是否首次开票 0：否，1:是"
		for (InvoiceBriefDto dto:list){
			Integer firstBilling = invoiceMapper.firstBilling(dto.getUserid()).equals(dto.getId()) ? 1 : 0;
			dto.setFirstBilling(firstBilling);

			dto.setSpecialRequirementsContent(map.get(dto.getCompid()));
			dto.setQuarterlyAmount(bigDecimalMap.get(dto.getUserid()));
			if (mapUser.get(dto.getUserid()) == 1){
				dto.setIsApprovalScreenshot(1);
			}
			if (mapCompany.get(dto.getCompid()) == 1){
				dto.setIsApprovalScreenshot(1);
			}
			if (dto.getProjectType() == ProjectType.CROWDSOURCE) {
				CrowdsourceProject cp = new CrowdsourceProject().selectById(dto.getProjectid());
				if (cp != null) {
					dto.setAsProtocol(cp.getAsProtocol());
				}
			}
		}

		return smartResultAll(list, page.getTotal(), page.getPages(), page.getPageNum(), sumPrice);
	}

	/**
	 * 查询 待申请 发票列表
	 *
	 * @param formBean
	 * @return
	 */
	public SmartResult pendingInvoiceList(BaseSimpleFormBean<InvoiceListFromBean> formBean) {
		InvoiceListFromBean reqdata = formBean.getReqdata();
		int userid = formBean.getUserid();
		if (userid <= 0 || reqdata == null) return errorParamSmartResult();
		SystemManager systemManager = new SystemManager().selectById(userid);
		if (null == systemManager || systemManager.getState() != 1) {
			return smartResult(StatusMsg.StatusMsg_128);
		}
		//操作人员对接城市
		String dockingCity = "";
		String city = systemManager.getDockingCity();
		if (StringUtil.isNotEmpty(city)) {
			// 发票 创客按自身的开户地区分
			dockingCity = " and ma.opening_location in (" + city + ") ";
		}
		Date startDate = reqdata.getStartDate();
		String name = reqdata.getName();
		String projectType = reqdata.getProjectType();
		Date endDate = reqdata.getEndDate();
		int state = reqdata.getState();
		int partyId = reqdata.getPartyId();
		if (startDate == null) startDate = new Date(0);
		if (endDate == null) endDate = new Date();

		Page<InvoiceBriefDto> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());
		//开票中,或已开票
		List<InvoiceBriefDto> list = invoiceMapper.getBriefList(projectType, name, state, startDate, endDate, dockingCity, null, partyId,0);
		return smartResult(list, page.getTotal(), page.getPages(), page.getPageNum());
	}

	/**
	 * 待开策略性开票列表
	 */
	public SmartResult<InvoiceBriefDto> strategyInvoiceList(BaseSimpleFormBean<InvoiceListFromBean> formBean) {
		int userid = formBean.getUserid();
		InvoiceListFromBean reqdata = formBean.getReqdata();
		if (userid <= 0 || reqdata == null) return errorParamSmartResult();

		SystemManager systemManager = new SystemManager().selectById(userid);
		if (null == systemManager || systemManager.getState() != 1) {
			return smartResult(StatusMsg.StatusMsg_128);
		}
		//操作人员对接城市
		String city = systemManager.getDockingCity();
		String dockingCity = "";
		if (StringUtil.isNotEmpty(city)) {
			dockingCity = " and ma.opening_location in (" + city + ") ";
		}

		Date startDate = reqdata.getStartDate();
		Date endDate = reqdata.getEndDate();
		String name = reqdata.getName();

		if (startDate == null) startDate = new Date(0);
		if (endDate == null) endDate = new Date();

		List<InvoiceBriefDto> list;
		Page<InvoiceBriefDto> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());
		//开票中,或已开票
		list = invoiceMapper.getStrategyBriefList(name, startDate, endDate, dockingCity, ProjectType.zhiduoduoProjectTypes(),0);
		//获取创客季度金额
		Set<Integer> userId =  new HashSet<>();
		//获取企业策略性内容
		Set<Integer> companyId =  new HashSet<>();
		for (InvoiceBriefDto dto:list){
			companyId.add(dto.getCompid());
			userId.add(dto.getUserid());
		}
		Map<Integer,String> map = getSpecialNeedsContent(companyId,2);
		Map<Integer,BigDecimal> bigDecimalMap = obtainQuarterlyAmount(userId);
		for (InvoiceBriefDto dto:list){
			dto.setSpecialRequirementsContent(map.get(dto.getCompid()));
			dto.setQuarterlyAmount(bigDecimalMap.get(dto.getUserid()));
		}
		return SmartResult.of(list, page);
	}

	/**
	 * 待开策略性开票列表
	 */
	public SmartResult<InvoiceBriefDto> crowdsourceStrategyInvoiceList(BaseSimpleFormBean<InvoiceListFromBean> formBean) {
		int userid = formBean.getUserid();
		InvoiceListFromBean reqdata = formBean.getReqdata();
		if (userid <= 0 || reqdata == null) return errorParamSmartResult();

		SystemManager systemManager = new SystemManager().selectById(userid);
		if (null == systemManager || systemManager.getState() != 1) {
			return smartResult(StatusMsg.StatusMsg_128);
		}
		Date startDate = reqdata.getStartDate();
		Date endDate = reqdata.getEndDate();
		String name = reqdata.getName();

		if (startDate == null) startDate = new Date(0);
		if (endDate == null) endDate = new Date();

		List<InvoiceBriefDto> list;
		Page<InvoiceBriefDto> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());
		//开票中,或已开票
		list = invoiceMapper.getCrowdsourceStrategyBriefList(name, startDate, endDate, 0);
		return SmartResult.of(list, page);
	}

	public SmartResult setStrategyInvoice(BaseListFormBean<StrategyInvoiceFormBean> formBean) {
		@Valid List<StrategyInvoiceFormBean> reqdata = formBean.getReqdata();
		for (StrategyInvoiceFormBean strategyInvoiceFormBean : reqdata) {
			int invoiceid = strategyInvoiceFormBean.getInvoiceid();
			Date strategyDate = strategyInvoiceFormBean.getStrategyDate();
			String strategyRemark = strategyInvoiceFormBean.getStrategyRemark();
			Invoice invoice = new Invoice().selectById(invoiceid);
			if (invoice == null || !ProjectType.isZhiduoduoProject(invoice.getProjectType())) {
				return SmartResult.fail(StatusMsg.StatusMsg_199);
			}

			invoice.setStrategy(Constants.TRUE).setStrategyDate(strategyDate).setStrategyRemark(strategyRemark).updateById();
		}

		return smartResult();
	}

	/**
	 * 从已验收的项目创建发票 传projectid,获取默认的发票内容
	 */
	public SmartResult createInvoice(BaseSimpleFormBean<Integer> formBean) {
		Integer invoiceid = formBean.getReqdata();
		Invoice invoice = new Invoice().selectById(invoiceid);
		Asserts.notNull(invoice);
		//之前的发票表中的邮箱是从企业表中直接复制进去的 若后来企业修改邮箱  获取发票内容时候不能拿到实时正确的邮箱
		//改为直接取企业表中的邮箱信息 并更新到发票表中
		Company company = new Company().selectById(invoice.getCompid());
		Asserts.notNull(company);
		invoice.setEmail(company.getCompemail()).updateById();
		//获取创客信息  返回真实姓名
		MakerAccount makerAccount = new MakerAccount().selectOne(
				Condition.create().eq("userid", invoice.getUserid()).eq("realname_auth", 5));
		invoice.setActualName(makerAccount.getRealname())
				.setIdno(makerAccount.getIdno());

		return smartResult(invoice);
	}

	/**
	 * 获取开票详情
	 */
	public SmartResult getInvoiceDetail(BaseSimpleFormBean<Integer> formBean) {

		Integer invoiceid = formBean.getReqdata();
		if (invoiceid == null || invoiceid <= 0) return errorParamSmartResult();

		return smartResult(new Invoice().selectById(invoiceid));
	}

	/**
	 * 提交修改发票内容,保存发票到表中
	 */
	public SmartResult submit(BaseSimpleFormBean<SubmitInvoiceFormBean> formBean) {

		SubmitInvoiceFormBean reqdata = formBean.getReqdata();
		if (reqdata == null || reqdata.getProjectid() <= 0 ||
				StringUtil.isAnyEmpty(reqdata.getCompname(), reqdata.getContent(), reqdata.getUsername())) {
			return errorParamSmartResult();
		}

		int invoiceid = reqdata.getInvoiceid();
		Invoice invoice = new Invoice().selectById(invoiceid);
		Asserts.notNull(invoice);
		//判断委托函发送通知
		CompanyAccount companyAccount = new CompanyAccount().selectOne("compid", invoice.getCompid());
		Asserts.notNull(companyAccount);

		MakerDetailDto makerInfo = makerService.getUserInfo(invoice.getUserid());
		if (makerInfo.getTemporaryLogin() == Constants.TRUE) {
			// 准创客(临时登录) 不需要判断库存
			BeanUtils.copyProperties(reqdata, invoice);
			invoice.setState(Constants.invoicestate_3).setAccepttime(new Date()).updateById();
			return smartResult();
		} else {
			// 判断库存数量
			InvoiceInventory inventory = new InvoiceInventory().selectById(invoice.getUserid());
			Asserts.notNull(inventory, StatusMsg.StatusMsg_220);

			boolean understock = false;
			Integer invoicetype = invoice.getInvoicetype();
			int hundredThousand = reqdata.getHundredThousand();
			int tenThousand = reqdata.getTenThousand();
			if (NumberUtil.equals(invoicetype, InvoiceType.GENERAL)) {
				understock = inventory.getGenHundredThousand() < hundredThousand || inventory.getGenTenThousand() < tenThousand;
			} else if (NumberUtil.equals(invoicetype, InvoiceType.SPECIAL)) {
				understock = inventory.getSpeHundredThousand() < hundredThousand || inventory.getSpeTenThousand() < tenThousand;
			}
			Asserts.notTrue(understock, StatusMsg.StatusMsg_220);
			BeanUtils.copyProperties(reqdata, invoice);
			invoice.setState(Constants.invoicestate_3).setAccepttime(new Date()).setManagerid(formBean.getUserid());
			if (invoice.updateById()) {
				invoiceInventoryService.recordInventoryOut(tenThousand, hundredThousand, invoice.getUserid(), invoice.getInvoicetype(),
						formBean.getUserid(), invoice.getId(), invoice.getProjectType());
				return smartResult();
			}
		}
		return optFailSmartResult();
	}

	/**
	 * 提交修改发票内容,保存发票到表中
	 */
	public SmartResult confirmPayAndSubmit(BaseSimpleFormBean<SubmitInvoiceFormBean> formBean) {

		SubmitInvoiceFormBean reqdata = formBean.getReqdata();
		if (reqdata == null || reqdata.getInvoiceid() <= 0 ||
				StringUtil.isAnyEmpty(reqdata.getCompname(), reqdata.getContent(), reqdata.getUsername())) {
			return errorParamSmartResult();
		}

		int invoiceid = reqdata.getInvoiceid();
		Invoice invoice = new Invoice().selectById(invoiceid);
		if (invoice == null) return smartResult(StatusMsg.StatusMsg_326);

		BeanUtils.copyProperties(reqdata, invoice, "projectid");
		invoice.setState(Constants.invoicestate_3).setAccepttime(new Date());

		if (invoice.updateById()) {
			new CompanyProject().setProjectid(invoice.getProjectid()).setInvoicecontent(invoice.getContent()).updateById();

			return smartResult();
		}

		return optFailSmartResult();
	}

	/**
	 * 确认已开发票,输入快递单号
	 */
	public SmartResult confirm(BaseSimpleFormBean<ConfirmInvoiceFormBean> formBean) {

		ConfirmInvoiceFormBean reqdata = formBean.getReqdata();
		if (reqdata == null) return errorParamSmartResult();
		//参数校验
		int type = reqdata.getType();
		String email = reqdata.getEmail();
		String express = reqdata.getExpress();
		String expressno = reqdata.getExpressno();
		int sendNotice = reqdata.getSendNotice();
		int taxCity = reqdata.getTaxCity();
		Integer companyId = reqdata.getCompanyId();
		int oneTenThousandNum = reqdata.getOneTenThousandNum();
		int oneHundredThousandNum = reqdata.getOneHundredThousandNum();
		if (type == 0 && StringUtil.isAnyEmpty(express, expressno)) return errorParamSmartResult();
		if (type == 1 && !StringUtil.isEmail(email)) return errorParamSmartResult();

		for (Integer id:reqdata.getId()){
			Invoice invoice = new Invoice().selectById(id);
			Asserts.notNull(invoice);
			// 针对 众包发票 进行处理
			if (reqdata.getOperationType() == 1) {

				if (companyId == null || companyId <= 0) return errorParamSmartResult();

				// 判断 主体企业 库存数量
				CompanyInventory companyInventory = new CompanyInventory().selectById(companyId);
				Asserts.notNull(companyInventory, StatusMsg.StatusMsg_220);
				Integer invoicetype = invoice.getInvoicetype();

				boolean understock = false;
				if (NumberUtil.equals(reqdata.getInvoicetype(), InvoiceType.GENERAL)) {
					understock = companyInventory.getGenHundredThousand() < oneHundredThousandNum ||
							companyInventory.getGenTenThousand() < oneTenThousandNum;
				} else if (NumberUtil.equals(reqdata.getInvoicetype(), InvoiceType.SPECIAL)) {
					understock = companyInventory.getSpeHundredThousand() < oneHundredThousandNum ||
							companyInventory.getSpeTenThousand() < oneTenThousandNum;
				}
				Asserts.notTrue(understock, StatusMsg.StatusMsg_220);
			}

			invoice.setTaxCity(taxCity)
					.setType(type)
					.setEmail(email)
					.setExpress(express)
					.setExpressno(expressno)
					.setManagerid(formBean.getUserid())
					.setState(Constants.invoicestate_4)
					.setFinishtime(new Date());
			invoice.setInvoicetype(reqdata.getInvoicetype());

			if (invoice.updateById()) {
				if (reqdata.getOperationType() == 1) {
					// 进行 主体企业库存出库 记录
					invoiceInventoryService.recordCompanyInventoryOut(oneTenThousandNum, oneHundredThousandNum, companyId,
							reqdata.getInvoicetype(), formBean.getUserid(), invoice.getId());
				}
				//通知微信模板消息，创客和企业都通知
				if (sendNotice == 1) {
					// 委托接单项目不需要给创客发消息
					if (!NumberUtil.equals(invoice.getProjectType(), ProjectType.ENTRUST_ZHIDUODUO)) {
						wxMessageService.sendInvoiceNotice(invoice.getId(), 1);
					}
					wxMessageService.sendInvoiceNotice(invoice.getId(), 2);
				}
				if (invoice.getProjectType() == 1) {
					//ceo通知提醒取消
					ceoNoticeService.cancelInvoiceNotice(invoice.getProjectid());
				}
				//众包项目同步运营主体
				if(NumberUtil.equals(invoice.getProjectType(),ProjectType.CROWDSOURCE)) {
					CrowdsourceProject crowdsourceProject = new CrowdsourceProject().selectById(invoice.getProjectid());
					if(crowdsourceProject != null) {
						crowdsourceProject.setPartyId(companyId).updateById();
					}
					CrowdsourceInvoice crowdsourceInvoice = new CrowdsourceInvoice().selectOne(Condition.create().eq("projectid", invoice.getProjectid()));
					if (crowdsourceInvoice != null){
						crowdsourceInvoice.setPartyId(companyId).updateById();
					}
				}
			}
			continue;
		}
		return smartResult();
	}

	/**
	 * 编辑发票备注
	 */
	public SmartResult editRemark(BaseSimpleFormBean<EditRemarkFormBean> formBean) {
		EditRemarkFormBean reqdata = formBean.getReqdata();
		Asserts.notNull(reqdata);

		int id = reqdata.getId();
		String remark = reqdata.getRemark();

		Invoice invoice = new Invoice().setId(id).setRemark(remark);

		if (!invoice.updateById()) return optFailSmartResult();
		return smartResult();
	}

	public SmartResult editInvoiceCancellation(BaseSimpleFormBean<EditInvoiceStateFormBean> formBean){
		EditInvoiceStateFormBean reqdata = formBean.getReqdata();
		Asserts.notNull(reqdata);

		Invoice invoice = new Invoice().setId(formBean.getReqdata().getInvoiceId())
									   .setCancellationReason(formBean.getReqdata().getCancellationReason())
									   .setCancellationEvidence(formBean.getReqdata().getCancellationEvidence())
									   .setManagerid(formBean.getUserid()) //记录操作人
									   .setState(Constants.invoicestate_6);

		if (invoice.updateById()) return smartResult();
		else return optFailSmartResult();
	}

	public SmartResult crowdsourceInvoiceList(BaseSimpleFormBean<InvoiceListFromBean> formBean) {
		int userid = formBean.getUserid();
		InvoiceListFromBean reqdata = formBean.getReqdata();
		Asserts.isTrue(userid > 0 && reqdata != null);

		Date startDate = reqdata.getStartDate();
		Date endDate = reqdata.getEndDate();
		String name = reqdata.getName();
		int state = reqdata.getState();
		int partyId = reqdata.getPartyId();

		SystemManager systemManager = new SystemManager().selectById(userid);
		if (null == systemManager || systemManager.getState() != 1) {
			return smartResult(StatusMsg.StatusMsg_128);
		}
		if (startDate == null) startDate = new Date(0);
		if (endDate == null) endDate = new Date();

		Page<InvoiceBriefDto> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());
		// 开票中,或已开票
		List<InvoiceBriefDto>  list = invoiceMapper.getBriefList(ProjectType.crowdsourceProjectTypes(), name, state, startDate, endDate, null, null, partyId,0);
		// 设置智众包项目数据
		for (InvoiceBriefDto dto : list) {
			CrowdsourceProject crowdsourceProject = new CrowdsourceProject().selectById(dto.getProjectid());
			if (crowdsourceProject != null) {
				CrowdsourceCompanyParty party = new CrowdsourceCompanyParty().selectById(crowdsourceProject.getPartyId());
				if(party != null){
					dto.setSubjectName(party.getCompanyName());
				}
				dto.setPayId(crowdsourceProject.getPayId());
				dto.setAsProtocol(crowdsourceProject.getAsProtocol());
			}

		}
		return smartResultPage(page);
	}

	public SmartResult<CompanyCrowdsourceInvoiceBriefStatisticDto> companyCrowdsourceInvoiceStatistic(
			BaseSimpleFormBean<Integer> formBean) {
		@Valid Integer compid = formBean.getReqdata();
		Date startDayOfMonth = DateUtil.getStartDayOfMonth(new Date());
		Date endDayOfMonth = DateUtil.getEndDayOfMonth(new Date());
		int finishedCount = invoiceMapper.countFinishedCompanyCrowdsourceInvoice(compid, startDayOfMonth);
		List<BigDecimal> list = invoiceMapper.getBriefListByCompidAndStates(ProjectType.CROWDSOURCE, compid, "", 0, startDayOfMonth,
				endDayOfMonth, "1,2").stream().map(InvoiceBriefDto::getInvoiceAmount).collect(Collectors.toList());
		CompanyCrowdsourceInvoiceBriefStatisticDto dto = new CompanyCrowdsourceInvoiceBriefStatisticDto().setCompid(compid)
				.setFinishedCount(finishedCount)
				.setPendingInvoiceList(list);
		return SmartResult.success(dto);
	}

	public SmartResult confirmCrowdsourceInvoiceApply(BaseSimpleFormBean<List<Integer>> formBean) {
		if (formBean.getReqdata().isEmpty()){
			return errorParamSmartResult();
		}
		for (Integer invoiceid :formBean.getReqdata()) {
			Invoice invoice = new Invoice().selectById(invoiceid);
			Asserts.notNull(invoice, StatusMsg.StatusMsg_326);
			Integer projectType = invoice.getProjectType();
			Asserts.isTrue(NumberUtil.intIn(projectType, ProjectType.CROWDSOURCE, ProjectType.ENTRUST_CROWDSOURCE), StatusMsg.StatusMsg_606);
			Asserts.isTrue(NumberUtil.equals(invoice.getState(), Constants.invoicestate_2), StatusMsg.StatusMsg_644);

			Integer projectid = invoice.getProjectid();
			if (NumberUtil.equals(projectType, ProjectType.CROWDSOURCE)) {
				CrowdsourceProject project = new CrowdsourceProject().selectById(projectid);
				Asserts.notNull(project, StatusMsg.StatusMsg_606);
				Date applyInvoiceDate = invoice.getApplyInvoiceDate();
				if (applyInvoiceDate == null) {
					invoice.setState(Constants.invoicestate_3);
				} else {
					// 同一月， 直接受理开票
					boolean sameMonth = DateUtil.isSameMonth(applyInvoiceDate, new Date());
					if (sameMonth || applyInvoiceDate.before(new Date())) {
						invoice.setState(Constants.invoicestate_3);
					} else {
						invoice.setStrategy(Constants.TRUE).setStrategyDate(applyInvoiceDate).setState(Constants.invoicestate_1);
					}
				}
			} else if (NumberUtil.equals(projectType, ProjectType.ENTRUST_CROWDSOURCE)) {
				EntrustmentProject project = new EntrustmentProject().selectById(projectid);
				Asserts.notNull(project, StatusMsg.StatusMsg_606);
				invoice.setState(Constants.invoicestate_3);
			}

			invoice.updateById();
		}
		return SmartResult.success();
	}

	public SmartResult editCrowdsourceInvoiceApplyDate(BaseSimpleFormBean<EditCrowdsourceApplyInvoiceDateFormBean> formBean) {
		@Valid EditCrowdsourceApplyInvoiceDateFormBean reqdata = formBean.getReqdata();
		int invoiceid = reqdata.getInvoiceid();
		Date applyInvoiceDate = reqdata.getApplyInvoiceDate();
		Invoice invoice = new Invoice().selectById(invoiceid);
		Asserts.notNull(invoice, StatusMsg.StatusMsg_326);
		Asserts.isTrue(invoice.getState() <= Constants.invoicestate_2, StatusMsg.StatusMsg_644);
		if (NumberUtil.equals(invoice.getProjectType(), ProjectType.CROWDSOURCE)) {
			CrowdsourceProject project = new CrowdsourceProject().selectById(invoice.getProjectid());
			Asserts.notNull(project, StatusMsg.StatusMsg_606);
			project.setApplyInvoiceDate(applyInvoiceDate);
			project.updateById();
		} else if (NumberUtil.equals(invoice.getProjectType(), ProjectType.ENTRUST_CROWDSOURCE)
				|| NumberUtil.equals(invoice.getProjectType(), ProjectType.MAKER_GROUPON_CROWDSOURCE)) {
			EntrustmentProject project = new EntrustmentProject().selectById(invoice.getProjectid());
			Asserts.notNull(project, StatusMsg.NATURAL_PROJECT_ERROR);
		} else {
			return SmartResult.ofErrorParam();
		}
		invoice.setApplyInvoiceDate(applyInvoiceDate);
		invoice.updateById();

		return SmartResult.success();
	}

	public void downloadInvoiceList(HttpServletResponse response, InvoiceListFromBean reqdata) {

		String name = reqdata.getName();
		int state = reqdata.getState();
		Date startDate = reqdata.getStartDate();
		Date endDate = reqdata.getEndDate();
		String projectType = reqdata.getProjectType();
		int partyId = reqdata.getPartyId();

		if (startDate == null) startDate = new Date((0));
		if (endDate == null) endDate = new Date();
		int managerid = reqdata.getManagerid();
		SystemManager systemManager = new SystemManager().selectById(managerid);
		if (null == systemManager || systemManager.getState() != 1) {
			throw new SmartException(StatusMsg.StatusMsg_101);
		}
		//操作人员对接城市
		String city = systemManager.getDockingCity();
		String dockingCity = "";
		if (StringUtil.isNotEmpty(city)) {
			dockingCity = " and ma.opening_location in (" + city + ") ";
		}
		List<InvoiceBriefDto> list = invoiceMapper.getBriefList(projectType, name, state, startDate, endDate, dockingCity, null, partyId,0);

		String file = RandomUtil.createRandomNo(name + "_发票列表_", "");
		try {
			list.stream().forEach((i) -> {
				SystemManager systemManager1 = new SystemManager().selectById(i.getManagerid());
				if (systemManager1 != null) {
					i.setManagerid(systemManager1.getManagername());
				} else {
					i.setManagerid(null);
				}
			});
			EasyExcel.write(getExcelOutPutStream(response, file), InvoiceBriefDto.class).sheet("发票列表").doWrite(list);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public SmartResult saveOfflinePayReceipt(BaseSimpleFormBean<OfflinePayReceiptFormBean> formBean) {
		@Valid OfflinePayReceiptFormBean reqdata = formBean.getReqdata();
		String receipt = reqdata.getPayReceipt();
		int invoiceid = reqdata.getId();

		new Invoice().setId(invoiceid).setPayReceipt(receipt).updateById();

		return smartResult();
	}

	public SmartResult addEditInventoryRecord(BaseSimpleFormBean<AddEditInventoryRecordFormBean> formBean) {
		@Valid AddEditInventoryRecordFormBean reqdata = formBean.getReqdata();
		Integer userid = reqdata.getUserid();
		MakerStudio studio = new MakerStudio().selectById(userid);
		if (studio == null) return smartResult(StatusMsg.StatusMsg_201);

		InvoiceInventoryRecord inventoryRecord = new InvoiceInventoryRecord().setId(reqdata.getId())
				.setUserid(userid)
				.setAdminid(formBean.getUserid())
				.setInvoiceType(reqdata.getInvoiceType())
				.setAmountType(reqdata.getAmountType())
				.setAmount(reqdata.getAmount())
				.setState(1);
		if (inventoryRecord.insertOrUpdate()) {
			return smartResult();
		}

		return optFailSmartResult();
	}

	public SmartResult entryInventory(BaseSimpleFormBean<String> formBean) {
		@Valid String ids = formBean.getReqdata();

		String[] arr = ids.split(",");
		for (int i = 0; i < arr.length; i++) {
			Integer id = StringUtil.toInt(arr[i]);
			invoiceInventoryService.recordInventoryIn(id);
		}
		return SmartResult.success();
	}

	public SmartResult deleteInventoryRecord(BaseSimpleFormBean<Integer> formBean) {
		@Valid Integer id = formBean.getReqdata();
		InvoiceInventoryRecord inventoryRecord = new InvoiceInventoryRecord().selectById(id);
		if (inventoryRecord == null) return smartResult(StatusMsg.StatusMsg_216);
		if (inventoryRecord.getState() == 2) return smartResult(StatusMsg.StatusMsg_218);

		new InvoiceInventoryRecord().deleteById(id);
		return smartResult();
	}

	public SmartResult<InvoiceInventoryDto> getInventoryList(BaseSimpleFormBean<InventoryListFormBean> formBean) {
		@Valid InventoryListFormBean reqdata = formBean.getReqdata();
		String name = reqdata.getName();
		SmartResult<SystemManager> systemManagerById = systemService.getSystemManagerById(formBean);
		Page<InvoiceInventoryDto> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());
		String dockingCity = systemManagerById.getObject().getDockingCity();
		invoiceInventoryMapper.findList(name, dockingCity);

		for (InvoiceInventoryDto dto : page) {
			BigDecimal sum = invoiceMapper.sumUnfinishInvoiceAmount(dto.getUserid(), 0);
			// 计算库存总金额
			int inventoryAmount = 10000 * (dto.getGenTenThousand() + dto.getSpeTenThousand()) +
					100000 * (dto.getGenHundredThousand() + dto.getSpeHundredThousand());
			dto.setPendingInvoiceAmount(sum).setInventoryAmount(BigDecimal.valueOf(inventoryAmount));
		}
		return smartResultPage(page);
	}

	public SmartResult<InvoiceInventoryDto> nothingInventoryList(BaseSimpleFormBean<InventoryListFormBean> formBean) {
		@Valid InventoryListFormBean reqdata = formBean.getReqdata();
		String name = reqdata.getName();

		Page<InvoiceInventoryDto> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());
		invoiceInventoryMapper.nothingInventoryList(name);

		for (InvoiceInventoryDto dto : page) {
			// 计算库存总金额
			int inventoryAmount = 10000 * (dto.getGenTenThousand() + dto.getSpeTenThousand()) +
					100000 * (dto.getGenHundredThousand() + dto.getSpeHundredThousand());
			dto.setInventoryAmount(BigDecimal.valueOf(inventoryAmount));
		}
		return smartResultPage(page);
	}

	public SmartResult<InvoiceInventoryRecordDto> getInventoryRecordList(BaseSimpleFormBean<InventoryRecordListFormBean> formBean) {
		@Valid InventoryRecordListFormBean reqdata = formBean.getReqdata();
		String name = reqdata.getName();
		Date startDate = reqdata.getStartDate();
		Date endDate = reqdata.getEndDate();
		if (startDate == null) startDate = DateUtil.getEpochTime();
		if (endDate == null) endDate = new Date();

		SmartResult<SystemManager> systemManagerById = systemService.getSystemManagerById(formBean);
		Page<InvoiceInventoryRecordDto> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());
		String dockingCity = systemManagerById.getObject().getDockingCity();
		List<InvoiceInventoryRecordDto> list = invoiceInventoryRecordMapper.findList(name, startDate, endDate, dockingCity);
		for (int i = 0; i < list.size(); i++) {
			InvoiceInventoryRecordDto invoiceInventoryRecordDto = list.get(i);
			if (invoiceInventoryRecordDto.getState() == 3 && invoiceInventoryRecordDto.getProjectType() != null) {
				if (invoiceInventoryRecordDto.getProjectType() == 1) {
					Invoice invoice = new Invoice().selectById(invoiceInventoryRecordDto.getInvoiceId());
					if(invoice != null) {
						invoiceInventoryRecordDto.setCompname(invoice.getCompname()).setManagerid(invoice.getManagerid()).setProjectname(invoice.getProjectname());
					}

				} else if (invoiceInventoryRecordDto.getProjectType() == 3) {
					TaxerInvoice taxerInvoice = new TaxerInvoice().selectById(invoiceInventoryRecordDto.getInvoiceId());
					if(taxerInvoice != null) {
						invoiceInventoryRecordDto.setCompname(taxerInvoice.getCompanyName()).setManagerid(taxerInvoice.getManagerid()).setProjectname(taxerInvoice.getProjectname());
					}
				}
			}
		}
		return smartResultPage(page);
	}

	/**
	 * 智众包成本发票列表
	 *
	 * @param formBean
	 * @return
	 */
	public SmartResult crowdsourceCostInvoiceList(BaseSimpleFormBean<CrowdsourceCostInvoiceListFromBean> formBean) {
		int userid = formBean.getUserid();
		CrowdsourceCostInvoiceListFromBean reqdata = formBean.getReqdata();
		if (userid <= 0 || reqdata == null) {
			return errorParamSmartResult();
		}
		int state = reqdata.getState();
		int strategy = reqdata.getStrategy();
		Date startDate = reqdata.getStartDate();
		Date endDate = reqdata.getEndDate();
		String startAmount = reqdata.getStartAmount();
		String endAmount = reqdata.getEndAmount();
		String companyName = reqdata.getCompanyName();
		String userName = reqdata.getUserName();
		int userType = reqdata.getUserType();
		String sort = reqdata.getSort();
		if (null == companyName) {
			companyName = "";
		}
		if (null == userName) {
			userName = "";
		}
		if (startDate == null) {
			startDate = new Date(0);
		}
		if (endDate == null) {
			endDate = new Date();
		}
		SystemManager systemManager = new SystemManager().selectById(userid);
		if (null == systemManager || systemManager.getState() != 1) {
			return smartResult(StatusMsg.StatusMsg_128);
		}
		//操作人员对接的城市
		String city = systemManager.getDockingCity();

		Date overdueWorkDay = DateUtil.addWorkDay(new Date(), -4);
		Date overdueNaturalDay = DateUtil.getDayChange(new Date(), -30);

		Page<Object> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());
		List<CrowdsourceCostInvoicefDto> list = crowdsourceInvoiceMapper.crowdsourceCostInvoiceList(userType, companyName, userName,
				startDate, endDate, startAmount, endAmount, state, strategy,city, sort, overdueNaturalDay, overdueWorkDay,reqdata.getOperatingSubject());
		//获取创客季度金额
		Set<Integer> userId =  new HashSet<>();
		//获取企业策略性内容
		Set<Integer> companyId =  new HashSet<>();
		for (CrowdsourceCostInvoicefDto dto:list){
			companyId.add(dto.getCompid());
			userId.add(dto.getCrowdsourceid());
		}
		Map<Integer,String> map = getSpecialNeedsContent(companyId,2);
		Map<Integer,BigDecimal> bigDecimalMap = obtainQuarterlyAmount(userId);

		BigDecimal totalAmount = BigDecimal.ZERO;
		for (CrowdsourceCostInvoicefDto c : list) {
			//是否首次开票 0：否，1:是"
			Integer firstBilling = crowdsourceInvoiceMapper.firstBilling(c.getCrowdsourceid()).equals(c.getId()) ? 1 : 0;
			c.setFirstBilling(firstBilling);
			totalAmount = totalAmount.add(c.getProjectAmount());

			c.setSpecialRequirementsContent(map.get(c.getCompid()));
			c.setQuarterlyAmount(bigDecimalMap.get(c.getCrowdsourceid()));
		}
		return smartResultAll(list, page.getTotal(), page.getPages(), page.getPageNum(), totalAmount);
	}

	/**
	 * 导出智众包成本发票列表 2022/1/16 wangtianteng
	 *
	 * @param response
	 */
	public void exportInvoiceData(HttpServletResponse response,int userType,String companyName,String userName,Date startDate,Date endDate,String startAmount,String endAmount,int state,int strategy,int managerid,String sort,int auth) {
		if (startDate == null) {
			startDate = new Date(0);
		}
		if (endDate == null) {
			endDate = new Date();
		}
		SystemManager systemManager = new SystemManager().selectById(managerid);
		if (null == systemManager || systemManager.getState() != 1) {
			throw new SmartException(StatusMsg.StatusMsg_128);
		}
		//操作人员对接的城市
		String city = systemManager.getDockingCity();
		Date overdueWorkDay = DateUtil.addWorkDay(new Date(), -4);
		Date overdueNaturalDay = DateUtil.getDayChange(new Date(), -30);

		if (null == companyName) {
			companyName = "";
		}
		if (null == userName) {
			userName = "";
		}

		//开票中,或已开票
		String file = RandomUtil.createRandomNo("成本票列表", "");
		List<CrowdsourceCostInvoicefDto> list = crowdsourceInvoiceMapper.crowdsourceCostInvoiceList(userType, companyName, userName,
				startDate, endDate, startAmount, endAmount, state, strategy,city, sort, overdueNaturalDay, overdueWorkDay,"");

		//获取创客季度金额
		Set<Integer> userId =  list.stream()
								   .map(CrowdsourceCostInvoicefDto::getCrowdsourceid)
								   .collect(Collectors.toSet());
		Map<Integer,BigDecimal> bigDecimalMap = obtainQuarterlyAmount(userId);
		for (CrowdsourceCostInvoicefDto c : list) {
			c.setQuarterlyAmount(bigDecimalMap.get(c.getCrowdsourceid()));
		}

		try {
			if (auth == 1) {
				EasyExcel.write(getExcelOutPutStream(response, file), CrowdsourceCostInvoicefDto.class).sheet("共青城发票列表").doWrite(list);
			} else {
				EasyExcel.write(getExcelOutPutStream(response, file), CrowdsourceCostInvoicefsDto.class).sheet("共青城发票列表").doWrite(list);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获取所有甲方信息
	 *
	 * @return
	 */
	public SmartResult partyCompanyList() {
		List<CrowdsourceCompanyParty> list = new CrowdsourceCompanyParty().selectList(Condition.create().orderBy("company_name", true));
		return smartResult(list);
	}

	/**
	 * 根据众包城市获取申请开票时对应的甲方信息
	 *
	 * @param formBean
	 * @return
	 */
	public SmartResult getPartyCompany(BaseSimpleFormBean<GetCompanyPartyFromBean> formBean) {
		if (null == formBean || 0 == formBean.getReqdata().getCrowdsourceCity()) {
			return errorParamSmartResult();
		}
		GetCompanyPartyFromBean getCompanyPartyFromBean = formBean.getReqdata();
		int crowdsourceCity = getCompanyPartyFromBean.getCrowdsourceCity();
		CityConfig cityConfig = new CityConfig().selectById(crowdsourceCity);
		if (null == cityConfig) {
			return smartResult(StatusMsg.StatusMsg_632);
		}
		if (0 == cityConfig.getPartyId()) {
			return smartResult(StatusMsg.StatusMsg_633);
		}
		CrowdsourceCompanyParty crowdsourceCompanyParty = new CrowdsourceCompanyParty().selectById(cityConfig.getPartyId());
		if (null == crowdsourceCompanyParty) {
			return smartResult(StatusMsg.StatusMsg_634);
		}
		return smartResult(crowdsourceCompanyParty);
	}

	/**
	 * 申请开票-选择甲方信息，输入运营方名称,选择开票地
	 *
	 * @param formBean
	 * @return
	 */
	public SmartResult applyForCostInvoice(BaseSimpleFormBean<ApplyForCostInvoiceFormBean> formBean) {
		if (null == formBean || null == formBean.getReqdata()) {
			return errorParamSmartResult();
		}
		ApplyForCostInvoiceFormBean reqdata = formBean.getReqdata();

		//获取该条发票信息
		CrowdsourceInvoice crowdsourceInvoice = new CrowdsourceInvoice().selectById(reqdata.getId());
		if (null == crowdsourceInvoice) {
			return smartResult(StatusMsg.StatusMsg_617);
		}
		crowdsourceInvoice.setPartyId(reqdata.getPartyId())
				.setEntrustedOperator(reqdata.getEntrustedOperator())
				.setInvoiceCityId(reqdata.getInvoiceCityId())
				.setProjectServiceName(reqdata.getProjectServiceName())
				.setState(Constants.CROWDSOURCE_INVOICE_STATE_2)
				.setInvoiceFlag(reqdata.getInvoiceFlag())
				//方便前端 接收字端名称未统一
				.setApplyForBillingRemarks(reqdata.getMergeRemarks());
		if (!crowdsourceInvoice.updateById()) {
			return smartResult(StatusMsg.StatusMsg_199);
		}
		return smartResult();
	}

	/**
	 * 成本发票——完成开票
	 *
	 * @param formBean
	 * @return
	 */
	public SmartResult completeCostInvoice(@RequestBody BaseSimpleFormBean<CompleteCostInvoiceFormBean> formBean) {
		if (null == formBean || null == formBean.getReqdata()) {
			return errorParamSmartResult();
		}
		CompleteCostInvoiceFormBean invoiceFormBean = formBean.getReqdata();
		if (0 == invoiceFormBean.getId()) {
			return errorParamSmartResult();
		}
		//获取该条发票信息
		CrowdsourceInvoice crowdsourceInvoice = new CrowdsourceInvoice().selectById(invoiceFormBean.getId());
		if (null == crowdsourceInvoice) {
			return smartResult(StatusMsg.StatusMsg_617);
		}
		//更新为 已开票
		crowdsourceInvoice.setInvoiceNumber(invoiceFormBean.getInvoiceNumber())
				.setInvoicePicture(invoiceFormBean.getInvoicePicture())
				.setRemarks(invoiceFormBean.getRemarks())
				.setState(Constants.CROWDSOURCE_INVOICE_STATE_3)
				.setFinishtime(new Date());
		if (1 == crowdsourceInvoice.getWhetherMerge()) {
			//为合并后的发票   需要把单条发票也给更新状态
			List<CostInvoiceListDto> list = crowdsourceProjectMapper.queryAllRelationCostInvoice(crowdsourceInvoice.getId());
			list.forEach(invoiceList -> {
				CrowdsourceInvoice singleInvoice = new CrowdsourceInvoice().selectById(invoiceList.getId());
				singleInvoice.setInvoiceNumber(invoiceFormBean.getInvoiceNumber())
						.setInvoicePicture(invoiceFormBean.getInvoicePicture())
						.setRemarks(invoiceFormBean.getRemarks())
						.setState(Constants.CROWDSOURCE_INVOICE_STATE_3)
						.setFinishtime(new Date())
						.updateById();
			});
		}
		if (!crowdsourceInvoice.updateById()) {
			return smartResult(StatusMsg.StatusMsg_199);
		}
		return smartResult();
	}

	/**
	 * 成本发票设置策略性待开票
	 *
	 * @param formBean formbean
	 * @return success
	 */
	public SmartResult setCostInvoiceToStrategy(BaseListFormBean<SetCostInvoiceToStrategyFormBean> formBean) {
		@Valid List<SetCostInvoiceToStrategyFormBean> reqdata = formBean.getReqdata();
		for (SetCostInvoiceToStrategyFormBean setCostInvoiceToStrategyFormBean : reqdata) {
			int invoiceid = setCostInvoiceToStrategyFormBean.getInvoiceid();
			Date strategyDate = setCostInvoiceToStrategyFormBean.getStrategyDate();
			String strategyRemark = setCostInvoiceToStrategyFormBean.getStrategyRemark();
			CrowdsourceInvoice crowdsourceInvoice = new CrowdsourceInvoice().selectById(invoiceid);
			if (null == crowdsourceInvoice) {
				return smartResult(StatusMsg.StatusMsg_617);
			}
			crowdsourceInvoice.setStrategy(Constants.TRUE).setStrategyDate(strategyDate).setStrategyRemark(strategyRemark).updateById();
		}
		return smartResult();
	}

	@Transactional
	public SmartResult mergeApplyForCostInvoice(@RequestBody BaseSimpleFormBean<MergeApplyForCostInvoiceFormBean> formBean) {
		if (null == formBean || null == formBean.getReqdata().getIds() || 2 > formBean.getReqdata().getIds().size() ||
				0 == formBean.getReqdata().getInvoiceCityId() || 0 == formBean.getReqdata().getType()) {
			return errorParamSmartResult();
		}
		MergeApplyForCostInvoiceFormBean invoiceFormBean = formBean.getReqdata();
		if (StringUtil.isAnyEmpty(invoiceFormBean.getEntrustedOperator(), invoiceFormBean.getProjectServiceName())) {
			return errorParamSmartResult();
		}
		List<Integer> ids = invoiceFormBean.getIds();
		BigDecimal amount = new BigDecimal("0");
		//创建一条新的发票数据
		CrowdsourceInvoice bigCrowdsourceInvoice = new CrowdsourceInvoice();
		//新增的合并后的发票数据 状态直接为开票中
		bigCrowdsourceInvoice.setProjectid(0)
				.setCrowdsourceid(0)
				.setCompname("")
				.setProjectAmount(amount)
				.setState(2)
				.setInvoiceCityId(invoiceFormBean.getInvoiceCityId())
				.setWhetherMerge(1)
				.insert();
		for (Integer id : ids) {
			CrowdsourceInvoice crowdsourceInvoice = new CrowdsourceInvoice().selectById(id);
			if (null == crowdsourceInvoice) {
				LogUtil.error("id为" + id + "的成本发票信息不存在");
				return smartResult(StatusMsg.StatusMsg_326);
			}
			int projectId = crowdsourceInvoice.getProjectid();
			int crowdsourceid = crowdsourceInvoice.getCrowdsourceid();
			//查看数据 若为空 说明选择的就不是自然人
			CrowdsourceProjectItem crowdsourceProjectItem = new CrowdsourceProjectItem().selectOne(
					Condition.create().eq("projectid", projectId).eq("userid", crowdsourceid).eq("user_type", 1));
			if (null == crowdsourceProjectItem) {
				return smartResult(StatusMsg.StatusMsg_643);
			}
			//多条开票记录中的开票金额相加
			amount = amount.add(crowdsourceInvoice.getProjectAmount());
			//被合并的发票数据关联到 新生成的数据上  并且也 更新到开票中的状态
			crowdsourceInvoice.setMergeId(bigCrowdsourceInvoice.getId())
					.setState(2)
					.setEntrustedOperator(invoiceFormBean.getEntrustedOperator())
					.setProjectServiceName(invoiceFormBean.getProjectServiceName())
					.setInvoiceCityId(invoiceFormBean.getInvoiceCityId())
					.updateById();
		}
		bigCrowdsourceInvoice.setProjectAmount(amount)
				.setEntrustedOperator(invoiceFormBean.getEntrustedOperator())
				.setProjectServiceName(invoiceFormBean.getProjectServiceName())
				.setType(invoiceFormBean.getType())
				.setMergeRemarks(invoiceFormBean.getMergeRemarks())
				.updateById();
		return smartResult();
	}

	/**
	 * 成本发票-合并开票列表
	 *
	 * @param formBean MergeCostInvoiceFrombean
	 * @return MergeCostInvoiceListDto
	 */
	public SmartResult<MergeCostInvoiceListDto> mergeCostInvoiceList(@RequestBody BaseSimpleFormBean<MergeCostInvoiceFrombean> formBean) {
		MergeCostInvoiceFrombean reqdata = formBean.getReqdata();
		int state = reqdata.getState();
		String name = reqdata.getName();
		Date startDate = reqdata.getStartDate();
		Date endDate = reqdata.getEndDate();
		if (startDate == null) {
			startDate = new Date(0);
		}
		if (endDate == null) {
			endDate = new Date();
		}
		Page<Object> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());
		List<MergeCostInvoiceListDto> list = crowdsourceProjectMapper.mergeCostInvoiceList(name, startDate, endDate, state);
		return smartResult(list, page.getTotal(), page.getPages(), page.getPageNum());
	}

	/**
	 * 查看关联的所有单条成本发票信息
	 *
	 * @param formBean integer
	 * @return CostInvoiceListDto
	 */
	public SmartResult<CostInvoiceListDto> queryAllRelationCostInvoice(@RequestBody BaseSimpleFormBean<Integer> formBean) {
		if (null == formBean.getReqdata()) {
			return errorParamSmartResult();
		}
		List<CostInvoiceListDto> list = crowdsourceProjectMapper.queryAllRelationCostInvoice(formBean.getReqdata());
		return smartResult(list);
	}

	/**
	 * 导出合并开票的明细
	 *
	 * @param response  response
	 * @param invoiceId 发票id
	 */
	public void exportMergeCostInvoiceInfo(HttpServletResponse response, int invoiceId) {

		List<CostInvoiceListDto> list = crowdsourceProjectMapper.queryAllRelationCostInvoice(invoiceId);

		String file = RandomUtil.createRandomNo("合并开票明细", "");
		try {
			EasyExcel.write(getExcelOutPutStream(response, file), CostInvoiceListDto.class).sheet("合并开票明细").doWrite(list);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 将未开票的成本票-合并开票下的自然人身份证文件压缩
	 *
	 * @param margeInvoiceList 合并成本票后的发票数据 （状态为开票中，身份证附件信息为空）
	 */
	public void mergeCostInvoiceIdNoInfoCompress(List<CrowdsourceInvoice> margeInvoiceList) {
		if (CollectionUtils.isEmpty(margeInvoiceList)) {
			return;
		}
		//遍历所有 合并后的开票数据
		for (CrowdsourceInvoice mergeInvoice : margeInvoiceList) {
			//获取关联该合并数据的所有发票信息
			List<CrowdsourceInvoice> beMergeCostInvoiceList = crowdsourceProjectMapper.queryBeMergeCostInvoice(mergeInvoice.getId());
			if (CollectionUtils.isEmpty(beMergeCostInvoiceList)) {
				continue;
			}
			//新建一个临时文件夹，将后续所有文件夹都放在这个文件夹下
			String temporaryFolderName = "temporaryFolder" + System.currentTimeMillis();
			File temporaryFolderFile = new File(uploadPathConfig.getUserLocal() + temporaryFolderName);
			if (!temporaryFolderFile.exists()) {
				if (!temporaryFolderFile.mkdirs()) {
					com.info.zhiduoduo.wxsdk.utils.LogUtil.error("压缩合并开票下自然人身份证文件-新建总的临时文件夹失败！");
					return;
				}
			}
			for (CrowdsourceInvoice crowdsourceInvoice : beMergeCostInvoiceList) {
				CrowdsourceAccount account = new CrowdsourceAccount().selectOne(
						Condition.create().eq("crowdsourceid", crowdsourceInvoice.getCrowdsourceid()));
				if (null != account) {
					//新建文件夹存放身份证图片信息
					String folderFileName = account.getRealname() + "+" + account.getIdno();
					File folderFile = new File(uploadPathConfig.getUserLocal() + temporaryFolderName + "/" + folderFileName);
					if (!folderFile.exists()) {
						if (!folderFile.mkdirs()) {
							com.info.zhiduoduo.wxsdk.utils.LogUtil.error("压缩成本发票合并开票下自然人身份证文件-新建存放身份证图片的文件夹失败！文件夹名称：" + folderFileName);
							continue;
						}
					}
					//复制身份证文件
					crowdsourceService.copyIdNoFile(account.getCrowdsourceid(), temporaryFolderName, folderFileName);
				} else {
					com.info.zhiduoduo.wxsdk.utils.LogUtil.error(
							"压缩成本发票合并开票下自然人身份证文件-没有查询到自然人信息！自然人ID：" + crowdsourceInvoice.getCrowdsourceid());
				}
			}
			com.info.zhiduoduo.wxsdk.utils.LogUtil.info("==========创建结束==========");
			com.info.zhiduoduo.wxsdk.utils.LogUtil.info("==========开始压缩==========");
			//oss路径
			String ossPath = uploadPathConfig.getUploadpath();
			//路径
			String path = "compressPackage/" + DateUtil.DateToStr("yyyyMMdd", new Date());
			//构建压缩包名称
			String fileName = mergeInvoice.getProjectServiceName() + "下自然人身份文件.zip";
			//压缩包存放路径
			String filePath = "";
			try {
				// 调用方法打包zip文件
				filePath = FileUtil.createZipFile(temporaryFolderFile.getPath(), ossPath, path, fileName);
			} catch (Exception e) {
				com.info.zhiduoduo.wxsdk.utils.LogUtil.error(
						"压缩合并开票下自然人身份证文件-将文件夹压缩为压缩包失败！生成时间：" + DateUtil.DateToStr("yyyy-MM-dd HH:mm", new Date()));
			} finally {
				// 压缩成功后删除项目中文件夹
				if (temporaryFolderFile.exists()) {
					FileUtil.delFiles(temporaryFolderFile);
				}
			}
			if (StringUtil.isEmpty(filePath)) {
				mergeInvoice.setEnclosureInfo("附件生成失败！").setGeneratetime(new Date()).updateById();
			} else {
				mergeInvoice.setEnclosureInfo("/" + filePath).setGeneratetime(new Date()).updateById();
			}
			com.info.zhiduoduo.wxsdk.utils.LogUtil.info("==========压缩结束==========");
		}
	}

	/**
	 * 获取 主体企业 库存清单列表
	 *
	 * @param formBean
	 * @return
	 */
	public SmartResult<CompanyInventoryDto> getMainEnterpriseInventoryList(BaseSimpleFormBean<InventoryListFormBean> formBean) {

		@Valid InventoryListFormBean reqdata = formBean.getReqdata();
		String name = reqdata.getName();

		Page<CompanyInventoryDto> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());
		companyInventoryMapper.findCompanyInventoryList(name);

		for (CompanyInventoryDto dto : page) {
			// 查询 当前企业 待开票 总金额
			BigDecimal sum = invoiceMapper.sumNotFinishCompanyInvoiceAmount(dto.getCompanyId(), 0);
			// 计算库存总金额
			int inventoryAmount = 10000 * (dto.getGenTenThousand() + dto.getSpeTenThousand()) +
					100000 * (dto.getGenHundredThousand() + dto.getSpeHundredThousand());
			dto.setPendingInvoiceAmount(sum).setInventoryAmount(BigDecimal.valueOf(inventoryAmount));
		}
		return smartResultPage(page);

	}

	/**
	 * 获取 主体企业的 发票出入库 记录列表
	 *
	 * @param formBean
	 * @return
	 */
	public SmartResult<CompanyInventoryRecordDto> getMainEnterpriseInventoryRecordList(
			@RequestBody BaseSimpleFormBean<InventoryRecordListFormBean> formBean) {

		@Valid InventoryRecordListFormBean reqdata = formBean.getReqdata();
		Date startDate = reqdata.getStartDate();
		Date endDate = reqdata.getEndDate();
		String name = reqdata.getName();
		if (startDate == null) startDate = DateUtil.getEpochTime();
		if (endDate == null) endDate = new Date();

		Page<CompanyInventoryRecordDto> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());
		companyInventoryRecordMapper.findCompanyInventoryRecordList(name, startDate, endDate);
		return smartResultPage(page);

	}

	/**
	 * 添加/编辑 主体企业 的发票出入库 记录
	 *
	 * @param formBean
	 * @return
	 */
	public SmartResult addEditMainEnterpriseInventoryRecord(BaseSimpleFormBean<MainEnterpriseInventoryRecordFormBean> formBean) {

		MainEnterpriseInventoryRecordFormBean reqdata = formBean.getReqdata();

		CompanyInventoryRecord inventoryRecord = new CompanyInventoryRecord().setId(reqdata.getId())
				.setCompanyId(reqdata.getCompanyId())
				.setAdminid(formBean.getUserid())
				.setInvoiceType(reqdata.getInvoiceType())
				.setAmountType(reqdata.getAmountType())
				.setInvoiceNum(reqdata.getInvoiceNum())
				.setState(1);
		if (inventoryRecord.insertOrUpdate()) {
			return smartResult();
		}

		return optFailSmartResult();

	}

	/**
	 * 对 发票进行 入库操作
	 *
	 * @param formBean
	 * @return
	 */
	public SmartResult entryCompanyInventory(BaseSimpleFormBean<String> formBean) {
		String ids = formBean.getReqdata();

		String[] arr = ids.split(",");
		for (int i = 0; i < arr.length; i++) {
			Integer id = StringUtil.toInt(arr[i]);
			invoiceInventoryService.recordCompanyInventoryIn(id);
		}
		return SmartResult.success();
	}

	/**
	 * 删除 主体企业 入库记录
	 *
	 * @param formBean
	 * @return
	 */
	public SmartResult deleteCompanyInventoryRecord(BaseSimpleFormBean<Integer> formBean) {
		@Valid Integer id = formBean.getReqdata();
		CompanyInventoryRecord inventoryRecord = new CompanyInventoryRecord().selectById(id);
		if (inventoryRecord == null) return smartResult(StatusMsg.StatusMsg_216);
		if (inventoryRecord.getState() != 1) return smartResult(StatusMsg.StatusMsg_218);
		new CompanyInventoryRecord().deleteById(id);
		return smartResult();
	}

	/**
	 * 每月定时将智众包项目发票的策略性开票转为开票中
	 */
	public void processCrowdsourceInvoiceStrategy() {
		Date currMonth = DateUtil.getStartDayOfMonth(DateUtil.nowDate());
		new Invoice().setState(Constants.invoicestate_3)
					 .update(Condition.create()
									  .eq("strategy_date", currMonth)
									  .eq("strategy", 1)
									  .in("project_type", Arrays.asList(ProjectType.CROWDSOURCE, ProjectType.ENTRUST_CROWDSOURCE))
									  .eq("state", Constants.invoicestate_1));

	}

	public void fixCrowdsourceInvoiceProjectItemId() {
		new Thread(() -> {
			List<CrowdsourceInvoice> invoiceList = new CrowdsourceInvoice().selectAll();
			Map<String, List<CrowdsourceInvoice>> invoiceMap = invoiceList.stream()
					.collect(Collectors.groupingBy(i -> StringUtils.joinWith("_", i.getProjectid(), i.getCrowdsourceid())));
			List<CrowdsourceInvoice> noItemIdList = Lists.newArrayList();
			for (Map.Entry<String, List<CrowdsourceInvoice>> entry : invoiceMap.entrySet()) {
				List<CrowdsourceInvoice> ivList = entry.getValue();
				String key = entry.getKey();
				List<Integer> list = StringUtil.splitToInt(key, "_");
				int projectid = list.get(0);
				int crowdsourceid = list.get(1);
				List<CrowdsourceProjectItem> itemList = new CrowdsourceProjectItem().selectList(
						Condition.create().eq("projectid", projectid).eq("userid", crowdsourceid));
				if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(itemList)) {
					// 该项目下的用户，只有1个发票，说明只有一个项目明细，如果有多个项目明细，也只取第一个
					if (ivList.size() == 1) {
						CrowdsourceInvoice iv = ivList.get(0);
						CrowdsourceProjectItem item = itemList.get(0);
						iv.setProjectItemId(item.getId()).setUserType(item.getUserType());
						iv.updateById();
					} else {
						// 同一用户有多个发票，则匹配金额相同的
						Map<Double, List<CrowdsourceInvoice>> ivAmountMap = ivList.stream()
								.collect(Collectors.groupingBy(ci -> ci.getProjectAmount().doubleValue()));
						Map<Double, List<CrowdsourceProjectItem>> itAmountMap = itemList.stream()
								.collect(Collectors.groupingBy(item -> item.getProjectAmount().doubleValue()));
						for (Map.Entry<Double, List<CrowdsourceInvoice>> ivEntry : ivAmountMap.entrySet()) {
							Double ivAmount = ivEntry.getKey();
							List<CrowdsourceInvoice> ivAmountList = ivEntry.getValue();
							List<CrowdsourceProjectItem> itAmountList = itAmountMap.get(ivAmount);
							if (!CollectionUtils.isEmpty(itAmountList)) {
								int itSize = itAmountList.size();
								for (int i = 0; i < ivAmountList.size(); i++) {
									CrowdsourceInvoice iv = ivAmountList.get(i);
									if (i < itSize) {
										CrowdsourceProjectItem item = itAmountList.get(i);
										iv.setProjectItemId(item.getId()).setUserType(item.getUserType());
										iv.updateById();
									} else {
										noItemIdList.add(iv);
									}
								}
							} else {
								noItemIdList.addAll(ivAmountList);
							}
						}
					}

				} else {
					noItemIdList.addAll(ivList);
				}

			}
			log.info("修复智众包成本发票项目ID， 没有匹配到项目明细的发票列表：{}", JSON.toJSONString(noItemIdList));

		}).start();
	}

	public SmartResult querymakerInvoiceSumPrice(BaseSimpleFormBean<QueryMakerInvoiceSumPriceFormBean> formBean) {
		if (formBean == null || formBean.getReqdata() == null) {
			return errorParamSmartResult();
		}
		Page<QueryMakerInvoiceSumPriceDto> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());
		invoiceMapper.querymakerInvoiceSumPrice(formBean.getReqdata().getCondition());
		return smartResult(page);
	}

	/**
	 * 编辑发票线下支付付款状态，增加发票线下付款记录
	 */
	@Transactional
	public SmartResult editInvoiceOfflinePayState(BaseSimpleFormBean<EditInvoicePayStateFormBean> formBean) {
		EditInvoicePayStateFormBean reqdata = formBean.getReqdata();
		Asserts.notNull(reqdata);

		int id = reqdata.getId();
		Invoice invoice = new Invoice().selectById(id);
		Asserts.notNull(invoice, StatusMsg.StatusMsg_326);
		Asserts.isTrue(Constants.OFFLINE_PAYING == invoice.getOfflinePayState(), StatusMsg.StatusMsg_361);

		boolean updateResult = invoice.setPaytime(new Date()).setOfflinePayState(Constants.OFFLINE_PAID).updateById();
		new CompanyProject().setProjectid(invoice.getProjectid()).setOfflinePayState(Constants.OFFLINE_PAID).updateById();
		if (!updateResult) {
			return optFailSmartResult();
		}

		//新增付款记录
		boolean insert = new InvoiceOfflinePayRecord().setInvoiceId(id)
				.setPayVoucher(reqdata.getPayVoucher())
				.setOfflineRemark(reqdata.getOfflineRemark())
				.setAdminid(formBean.getUserid())
				.setCreatetime(new Date())
				.insert();
		if (!insert) {
			return optFailSmartResult();
		}
		//新增收费记录
		RechargeRecord rechargeRecord = new RechargeRecord();
		rechargeRecord.setRechargeTypeId(Constants.RECHARGE_OFFLINE_SERVICE_FEE)
				.setRechargeAmount(invoice.getPayAmount())
				.setCustomerType(1)
				.setCustomerId(invoice.getUserid())
				.setCustomerName(invoice.getUsername())
				.setRechargeRemark(reqdata.getOfflineRemark())
				.setRechargeVoucher(reqdata.getPayVoucher())
				.setCreatedBy(formBean.getUserid())
				.setRechargeTime(new Date());
		rechargeRecord.insert();

		return smartResult();
	}

	/**
	 * 线下银行模式发票查询接口
	 *
	 * @param formBean
	 * @return
	 */
	public SmartResult<QueryInvoiceDto> queryApplyInvoiceList(BaseSimpleFormBean<QueryInvoiceListFromBean> formBean) {
		QueryInvoiceListFromBean reqdata = formBean.getReqdata();
		Date startDate = reqdata.getStartDate();
		Date endDate = reqdata.getEndDate();
		if (startDate == null) startDate = new Date(0);
		if (endDate == null) endDate = new Date();

		//开票中,或已开票
		Page<QueryInvoiceDto> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());
		List<QueryInvoiceDto> list = invoiceMapper.queryApplyInvoiceList(reqdata.getName(), reqdata.getOfflinePayState(), startDate,
				endDate, reqdata.getTemporaryLogin(), reqdata.getProjectType(), reqdata.getInvoiceState());
		return smartResult(list, page.getTotal(), page.getPages(), page.getPageNum());
	}

	public SmartResult editEnturstProjectInvoice(BaseSimpleFormBean<EditEntrustProjectInvoiceFormBean> formBean) {
		EditEntrustProjectInvoiceFormBean reqdata = formBean.getReqdata();
		int type = reqdata.getType();
		String ids = reqdata.getIds();
		String name = reqdata.getName();
		String content = reqdata.getContent();
		String invoiceContent = reqdata.getInvoiceContent();
		Integer categoryid = reqdata.getCategoryid();

		List<Integer> invoiceIds = StringUtil.splitToInt(ids, ",");
		List<Object> finishedInvoiceList = Lists.newArrayList();
		for (Integer id : invoiceIds) {
			if (type == EditEntrustProjectInvoiceFormBean.ZDD_INVOICE || type == EditEntrustProjectInvoiceFormBean.CROWDSOURCE_INVOICE) {
				Invoice invoice = new Invoice().selectById(id);
				if (invoice == null) continue;
				Integer state = invoice.getState();
				if (NumberUtil.equals(state, 4)) {
					finishedInvoiceList.add(invoice);
				} else {
					invoice.setContent(invoiceContent).setProjectname(name).updateById();
					new EntrustmentProjectItem().setName(name)
							.setContent(content)
							.setCategoryid(categoryid)
							.setInvoiceContent(invoiceContent)
							.update(Condition.create().eq("entrustee_id", invoice.getUserid()).eq("import_id", invoice.getProjectid()));
				}
			} else if (type == EditEntrustProjectInvoiceFormBean.CROWDSOURCE_COST_INVOICE) {
				CrowdsourceInvoice invoice = new CrowdsourceInvoice().selectById(id);
				if (invoice == null) continue;
				Integer state = invoice.getState();
				if (NumberUtil.equals(state, 3)) {
					finishedInvoiceList.add(invoice);
				} else {
					invoice.setInvoiceContent(invoiceContent).setProjectName(name).updateById();
					new EntrustmentProjectItem().setName(name)
							.setContent(content)
							.setCategoryid(categoryid)
							.setInvoiceContent(invoiceContent)
							.update(Condition.create()
									.eq("entrustee_id", invoice.getCrowdsourceid())
									.eq("import_id", invoice.getProjectid()));
				}
			}
		}

		return SmartResult.success(finishedInvoiceList);
	}

	public void checkZddInvoiceCompanyEntrustFile() {

		// 获取昨天完成的所有发票列表
		Date yesterday = DateUtil.getYesterday();
		List<Invoice> invoices = invoiceMapper.listFinishedByDate(yesterday);

		// 所有企业名称
		List<String> compnames = Lists.newArrayList();
		// 商务经理对应的企业名称
		Map<Integer, List<String>> bmCompnames = Maps.newHashMap();
		// 跟单员对应的企业名称
		Map<Integer, List<String>> merCompnames = Maps.newHashMap();

		for (Invoice invoice : invoices) {
			CompanyAccount account = companyAccountMapper.getByCompid(invoice.getCompid());
			if (account == null) continue;
			CompanyEntrustFile entrustFile = companyEntrustFileMapper.getByCompid(invoice.getCompid());
			if (entrustFile == null) continue;

			// 判断是否为无效的委托协议，无效则需要通知
			if (StringUtil.isEmpty(entrustFile.getEntrustFile()) || DateUtil.isExpired(entrustFile.getEntrustEndTime())) {
				String compname = invoice.getCompname();
				compnames.add(compname);
				// 商务经理
				Integer businessManagerId = account.getBusinessManagerId();
				if (NumberUtil.safeInt(businessManagerId) > 0) {
					List<String> bmNames = bmCompnames.computeIfAbsent(businessManagerId, bmid -> Lists.newArrayList());
					bmNames.add(compname);
				}
				// 跟单员
				Integer merchandiserId = account.getMerchandiserId();
				if (NumberUtil.safeInt(merchandiserId) > 0) {
					List<String> merNames = merCompnames.computeIfAbsent(merchandiserId, merid -> Lists.newArrayList());
					merNames.add(compname);
				}
			}
		}

		// 发送消息
		String format = "以下$d家企业未上传委托函，请及时跟进：%s。";
		if (!CollectionUtils.isEmpty(compnames)) {
			// riley, 特殊的商务经理通知
			int count = compnames.size();
			String names = StringUtils.join(compnames, "、");
			commonService.sendEnterpriseWeChatNotice(notificationConfig.getRileyManagerId(), null, 1, String.format(format, count, names));
		}
		// 商务经理
		if (!CollectionUtils.isEmpty(bmCompnames)) {
			bmCompnames.forEach((id, list) -> {
				// 发送给企业的商务经理
				int count = list.size();
				String names = StringUtils.join(list, "、");
				commonService.sendEnterpriseWeChatNotice(id, null, 1, String.format(format, count, names));
			});
		}
		// 跟单员
		if (!CollectionUtils.isEmpty(merCompnames)) {
			merCompnames.forEach((id, list) -> {
				// 发送给企业的跟单员
				int count = list.size();
				String names = StringUtils.join(list, "、");
				commonService.sendEnterpriseWeChatNotice(id, null, 1, String.format(format, count, names));
			});
		}
	}

	/**
	 * 发票未开预警：
	 * 1、成本票创客：每天发统计数量给赵菲、夏伦聪。
	 * 	逾期条件：已开税户的按4个工作日预警，未开税户的超过30天预警
	 * 	消息内容（【成本票已逾期】：金额30000元，数量30条，请尽快处理哦！
	 */
	public void checkCrowdsourceCostInvoiceRemind(){
		Date overdueWorkDay = DateUtil.addWorkDay(new Date(), -4);
		Date overdueNaturalDay = DateUtil.getDayChange(new Date(), -30);
		CrowdsourceCostInvoiceRemindDto remindDto = crowdsourceInvoiceMapper.costInvoiceUnInvoicedList(overdueWorkDay, overdueNaturalDay);
		String remindContent = String.format("【成本票已逾期】：数量%s条，请尽快处理哦！", remindDto.getUnInvoicedNum());
//		String remindContent = String.format("【成本票已逾期】：金额%s元，数量%s条，请尽快处理哦！", remindDto.getUnInvoicedAmount(), remindDto.getUnInvoicedNum());

		wxMessageService.invoiceOverdueNotice(remindContent,1);
	}

	/**
	 * 2、众包发票逾期条件：每月15号-25号每天16点发给夏伦聪、符嘉琳 纪锦娟
	 *  统计还未开票的（统计待确认和开票中），选择了开票日期的话，统计开票日期是小于等于当前月的
	 *  消息内容按运营主体统计：（【发票已逾期】芜湖信圣科技发展有限公司：金额1000元，数量4条；徐州法圣信息技术有限公司：金额2000元，数量6条。请尽快处理哦！）
	 */
	public void checkCrowdsourceInvoiceRemind(){
		String projectTypes = ProjectType.crowdsourceProjectTypes();
		Date currentMonth = DateUtil.getThisMonthBeginDate();
		List<CrowdsourceInvoiceRemindDto> remindDtoList = crowdsourceInvoiceMapper.crowdsourceUnInvoicedList(projectTypes,currentMonth);
		if (CollectionUtils.isEmpty(remindDtoList)) {
			return;
		}
		StringBuffer sb = new StringBuffer("【发票已逾期】");
		for (CrowdsourceInvoiceRemindDto remindDto : remindDtoList) {
			sb.append(String.format("%s：金额%s元，数量%s条；", remindDto.getPartyName(), remindDto.getUnInvoicedAmount(), remindDto.getUnInvoicedNum()));
		}
		wxMessageService.invoiceOverdueNotice(sb.toString() + "请尽快处理哦！",2);

	}

	/**
	 * 查询税源地列表
	 * @return
	 */
	public SmartResult queryTaxSourceList(){
		List<TaxSource> taxSourceList = new TaxSource().selectList(Condition.create());
		return smartResult(taxSourceList);
	}

	/**
	 * 申请开票
	 * @param formBean
	 * @return
	 */
	public SmartResult applyContractorInvoice(BaseSimpleFormBean<EditContractorInvoiceFormBean> formBean) {
		EditContractorInvoiceFormBean reqdata = formBean.getReqdata();
		ContractorInvoice invoice = new ContractorInvoice().selectById(reqdata.getInvoiceId());
		if(invoice == null){
			return smartResult(StatusMsg.StatusMsg_326);
		}
		invoice.setState(Constants.CROWDSOURCE_INVOICE_STATE_2)
			   .setPartyId(reqdata.getPartyId())
			   .setInvoiceCityId(reqdata.getInvoiceCityId())
			   .setRemarks(reqdata.getRemarks())
			   .setOperator(formBean.getUserid())
			   .updateById();
		return smartResult();
	}

	/**
	 * 确认智零工开票信息
	 * @param formBean
	 * @return
	 */
	public SmartResult confirmContractorInvoice(BaseSimpleFormBean<EditContractorInvoiceFormBean> formBean) {
		EditContractorInvoiceFormBean reqdata = formBean.getReqdata();
		ContractorInvoice invoice = new ContractorInvoice().selectById(reqdata.getInvoiceId());
		if(invoice == null){
			return smartResult(StatusMsg.StatusMsg_326);
		}
		invoice.setState(Constants.CROWDSOURCE_INVOICE_STATE_3)
			   .setInvoiceNumber(reqdata.getInvoiceNumber())
			   .setInvoicePicture(reqdata.getInvoicePicture())
			   .setRemarks(reqdata.getRemarks())
			   .setOperator(formBean.getUserid())
			   .setFinishtime(reqdata.getFinishtime())
			   .setInvoicedAmount(reqdata.getInvoicedAmount())
			   .updateById();
		return smartResult();
	}

	/**
	 * 作废智零工发票信息
	 * @param formBean
	 * @return
	 */
	public SmartResult cancelContractorInvoice(BaseSimpleFormBean<EditContractorInvoiceFormBean> formBean) {
		EditContractorInvoiceFormBean reqdata = formBean.getReqdata();
		ContractorInvoice invoice = new ContractorInvoice().selectById(reqdata.getInvoiceId());
		if(invoice == null){
			return smartResult(StatusMsg.StatusMsg_326);
		}
		invoice.setState(Constants.CROWDSOURCE_INVOICE_STATE_4)
			   .setInvalidationReasons(reqdata.getInvalidationReasons())
			   .setOperator(formBean.getUserid())
			   .updateById();
		return smartResult();
	}

	/**
	 * 查询发票列表
	 * @param formBean
	 * @return
	 */
	public SmartResult contractorInvoiceList(BaseSimpleFormBean<QueryContractorInvoiceFormBean> formBean){
		QueryContractorInvoiceFormBean reqdata = formBean.getReqdata();

		Date startDate = reqdata.getStartDate();
		Date endDate = reqdata.getEndDate();
		if (startDate == null) {
			startDate = new Date(0);
		}
		if (endDate == null) {
			endDate = new Date();
		}

		Page<ContractorInvoicefDto> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());
		List<ContractorInvoicefDto> list = contractorInvoiceMapper.contractorInvoiceList(reqdata.getCompanyName(),reqdata.getState(),startDate,endDate);
		return smartResultPage(page);
	}


	public SmartResult addBuyer(BaseSimpleFormBean<PurchaseInformation> formBean){
		PurchaseInformation reqdata = formBean.getReqdata();
		if (reqdata.getPurchaserId() == null || reqdata.getPurchaserId() == 0 ){
			PurchaseInformation purchaseInformation = new PurchaseInformation();
			purchaseInformation.setPurchaserName(reqdata.getPurchaserName())
					.setBankInformation(reqdata.getBankInformation())
					.setDutyParagraph(reqdata.getDutyParagraph()).insert();
			return smartResult(purchaseInformation.getPurchaserId());
		}else {
			PurchaseInformation pi = purchaseInformationMapper.selectById(reqdata.getPurchaserId());
			if (null == pi){
				return smartResult(StatusMsg.StatusMsg_102);
			}
			pi.setPurchaserName(reqdata.getPurchaserName())
					.setBankInformation(reqdata.getBankInformation())
					.setDutyParagraph(reqdata.getDutyParagraph()).updateById();
			return smartResult(pi.getPurchaserId());
		}
	}

	public SmartResult deletionOfPurchaser(Integer id){
		PurchaseInformation pi = purchaseInformationMapper.selectById(id);
		if (null == pi){
			return smartResult(StatusMsg.StatusMsg_102);
		}
		pi.setIsDelete(1).updateById();
		return smartResult(pi.getPurchaserId());

	}

	public SmartResult inquireAboutTheBuyer(BaseSimpleFormBean<inquireAboutTheBuyerFormBean> formBean){
		inquireAboutTheBuyerFormBean reqdata = formBean.getReqdata();
		List<PurchaseInformation> list = purchaseInformationMapper
				.selectList(Condition.create().like("purchaser_name", reqdata.getPurchaserName())
						.eq("is_delete",0));
		return smartResult(list);
	}

	public SmartResult inquireAboutTheBuyerList(BaseSimpleFormBean<inquireAboutTheBuyerFormBean> formBean){
		inquireAboutTheBuyerFormBean reqdata = formBean.getReqdata();
		Page<PurchaseInformation> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());
		List<PurchaseInformation> list = purchaseInformationMapper
				.selectList(Condition.create().like("purchaser_name", reqdata.getPurchaserName())
						.eq("is_delete",0));
		return smartResultPage(page);
	}
	public SmartResult addPurchaseInvoiceRecord(BaseSimpleFormBean<PurchaseInvoiceRecord> formBean){
		PurchaseInvoiceRecord reqdata = formBean.getReqdata();
		Company company = companyMapper.selectById(reqdata.getCompanyId());
		if (null == company){
			return smartResult(StatusMsg.StatusMsg_102);
		}
		if (reqdata.getId() == null || reqdata.getId() == 0 ){
			PurchaseInvoiceRecord purchaseInvoiceRecord = new PurchaseInvoiceRecord();
			purchaseInvoiceRecord.setPurchaserName(reqdata.getPurchaserName())
					.setCompanyId(reqdata.getCompanyId())
					.setInvoiceType(reqdata.getInvoiceType())
					.setDutyParagraph(reqdata.getDutyParagraph())
					.setBankInformation(reqdata.getBankInformation())
					.setInvoicedAmount(reqdata.getInvoicedAmount())
					.setInvoicingCategory(reqdata.getInvoicingCategory())
					.setReceipt(reqdata.getReceipt())
					.setEnteredBy(formBean.getUserid()).insert();
			return smartResult();
		}else {
			PurchaseInvoiceRecord purchaseInvoiceRecord = purchaseInvoiceRecordMapper.selectById(reqdata.getId());
			purchaseInvoiceRecord.setInvoiceType(reqdata.getInvoiceType())
					.setDutyParagraph(reqdata.getDutyParagraph())
					.setBankInformation(reqdata.getBankInformation())
					.setInvoicedAmount(reqdata.getInvoicedAmount())
					.setInvoicingCategory(reqdata.getInvoicingCategory())
					.setReceipt(reqdata.getReceipt())
					.setPurchaserName(reqdata.getPurchaserName()).updateById();
			return smartResult();
		}
	}

	public SmartResult confirmationOfBill(BaseSimpleFormBean<inquireAboutTheBuyerFormBean> formBean,int type){
		inquireAboutTheBuyerFormBean reqdata = formBean.getReqdata();
		PurchaseInvoiceRecord purchaseInvoiceRecord = purchaseInvoiceRecordMapper.selectById(reqdata.getId());
		if (null == purchaseInvoiceRecord){
			return smartResult(StatusMsg.StatusMsg_102);
		}
		//确认开票
		if (null != reqdata.getInvoicedDate()){
			purchaseInvoiceRecord.setInvoicedDate(reqdata.getInvoicedDate()).setState(2);
		}
		//保存证据链
		if (null != reqdata.getChainOfEvidence()){
			purchaseInvoiceRecord.setChainOfEvidence(reqdata.getChainOfEvidence());
		}
		//状态等于2等于删除
		if (type == 2){
			purchaseInvoiceRecord.setIsDelete(1);
		}
		purchaseInvoiceRecord.updateById();
		return smartResult();

	}
	public SmartResult purchaseInvoiceRecordList(BaseSimpleFormBean<inquireAboutTheBuyerFormBean> formBean){
		Page<PurchaseInvoiceRecordListDto> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());
		List<PurchaseInvoiceRecordListDto> list = purchaseInvoiceRecordMapper.
				purchaseInvoiceRecordList(formBean.getReqdata().getState(),
						formBean.getReqdata().getInvoiceType(),
						formBean.getReqdata().getPurchaserName(),
						formBean.getReqdata().getCompanyName());
		return smartResultPage(page);
	}
	/**
	 * 智零工成本票逾期
	 * 每天9点发统计数量发给 cindy 和 胡刚。
	 */
	public void reminderOfOverdueCostTicket(){
		//周六周日不发通知
		if (!DateUtil.isWeekend(new Date())) {
			Date date = DateUtil.addWorkDay(new Date(), -7);
			int count = contractorInvoiceMapper.reminderOfOverdueCost(date);
			if (count != 0) {
				//发信息给cindy
				wxMessageService.costTicketOverdue("有" + count + "条发票已逾期，请尽快处理！");
				//通知胡刚
				new Thread(() -> commonService.enterpriseAutomaticFreezing(28, "智零工成本票有" + count + "条发票已逾期。")).start();
			}
		}
	}
	/**
	 * 税单逾期
	 * 25号统计发给 cindy 和 胡刚 tina。
	 */
	public void overdueTaxForm(){
		//上个月完税凭证
		String date = DateUtil.getString(new Date(),DateUtil.FORMAT_STYLE_10);
		List<TaxClearanceCertificateDto> list = contractorInvoiceMapper
				.taxClearanceCertificate(null,null,date);
		if (!CollectionUtils.isEmpty(list)){
			StringBuffer content =  new StringBuffer("有"+list.size()+"张完税凭证逾期未上传，请及时处理!");
			//发信息给cindy
			wxMessageService.overdueTaxCertificate(content.toString(), "oB8CR0Y8d_AK9BFtDW0vvzdJjTNw" );
			//发信息给tina
			wxMessageService.overdueTaxCertificate(content.toString(), notificationConfig.getTestNoticeOpenids().get(2));
			//通知胡刚和tina
			StringBuffer contentBoss =  new StringBuffer("有"+list.size()+"张完税凭证逾期未上传:");
			int i = 0;
			for (TaxClearanceCertificateDto source:list){
				i++;
				contentBoss.append(String.format("%s、逾期月份:%s,税源地:%s;",i,source.getDate(),source.getTaxSourceName()));
			}
			new Thread(() -> commonService.enterpriseAutomaticFreezing(28,contentBoss.toString())).start();
			new Thread(() -> commonService.enterpriseAutomaticFreezing(44,contentBoss.toString())).start();
		}
	}
	/**
	 * 获取特殊需求内容
	 */
	public Map<Integer,String> getSpecialNeedsContent(Set<Integer> id,int type){
		Map<Integer,String> map = new HashMap<>();
		for (Integer ids:id){
			map.put(ids, platformMemorandumMapper.getSpecialNeedsContent(ids,type));
		}
		return map;
	}
	/**
	 * 获取季度金额
	 */
	public Map<Integer,BigDecimal> obtainQuarterlyAmount(Set<Integer> id){
		Map<Integer,BigDecimal> map = new HashMap<>();
		for (Integer ids:id){
			map.put(ids, invoiceMapper.obtainQuarterlyAmount(ids));
		}
		return map;
	}
	/**
	 * 获取不策略开票
	 */
	public Map<Integer,Integer> getNoPolicyBilling(Set<Integer> id,int type){
		Map<Integer,Integer> map = new HashMap<>();
		for (Integer ids:id){
			 Integer typeS = platformMemorandumMapper.getType(ids,type);
			 if (typeS != null){
				 map.put(ids,1);
			 }else {
				 map.put(ids,0);
			 }

		}
		return map;
	}
	/**
	 * 上传30万审批截图
	 * @param formBean
	 * @return
	 */
	public SmartResult approvalScreenshot(ApprovalScreenshotFromBean formBean) {
		for(Integer id:formBean.getInvoiceId()){
			Invoice invoice = invoiceMapper.selectById(id);
			if (null == invoice){
				continue;
			}
			invoice.setApprovalScreenshot(formBean.getApprovalScreenshot()).updateById();
		}
		return smartResult();
	}
	/**
	 * 替换发票路径
	 * @param formBean
	 * @return
	 */
	public SmartResult replaceTheInvoicePath(TheInvocePathFromBean formBean) {
		CrowdsourceInvoice invoice = crowdsourceInvoiceMapper.selectById(formBean.getId());
		if (null == invoice){
			return smartResult(StatusMsg.StatusMsg_102);
		}
		return smartResult(invoice.setInvoicePicture(formBean.getApprovalScreenshot()).updateById());
	}
	public SmartResult<TaxClearanceCertificateDto> taxClearanceCertificate(BaseSimpleFormBean<TaxPaymentVoucherListFormBean> formBean) {
		Page<TaxClearanceCertificateDto> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());
		List<TaxClearanceCertificateDto> list = contractorInvoiceMapper
				.taxClearanceCertificate(formBean.getReqdata().getTaxSourceId(),formBean.getReqdata().getOperatingEntityId(),null);
		return smartResult(list, page.getTotal(), page.getPages(), page.getPageNum());
	}

}
